<script setup>
import { ref, computed, watch } from 'vue'

// Props 定义
const props = defineProps({
  modelValue: {
    type: [Date, Array, null],
    default: null
  },
  minDate: {
    type: Date,
    default: null
  },
  maxDate: {
    type: Date,
    default: null
  },
  format: {
    type: String,
    default: 'YYYY-MM-DD'
  },
  disabled: {
    type: Boolean,
    default: false
  },
  placeholder: {
    type: String,
    default: '请选择日期'
  },
  firstDayOfWeek: {
    type: Number,
    default: 1
  },
  showWeekNumbers: {
    type: Boolean,
    default: false
  },
  isRange: {
    type: Boolean,
    default: false
  },
  locale: {
    type: [String, Object],
    default: 'zh-CN'
  },
  isInline: {
    type: Boolean,
    default: false
  },
  className: {
    type: String,
    default: ''
  },
  showConfirmButton: {
    type: Boolean,
    default: true
  },
  confirmText: {
    type: String,
    default: '确认'
  },
  disableDate: {
    type: Function,
    default: () => false
  }
})

const emit = defineEmits(['update:modelValue', 'change', 'confirm', 'open', 'close', 'invalid'])

// 初始化状态
const currentDate = ref(new Date())
const selectedDate = ref(props.isRange ? [] : null)
const isOpen = ref(props.isInline)

// 格式化单个日期
const formatSingleDate = (date) => {
  if (!(date instanceof Date) || isNaN(date.getTime())) return ''
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return props.format
    .replace('YYYY', year)
    .replace('MM', month)
    .replace('DD', day)
}

// 格式化显示日期
const formattedDate = computed(() => {
  if (!selectedDate.value) return ''
  if (Array.isArray(selectedDate.value)) {
    return selectedDate.value
      .map(date => date instanceof Date ? formatSingleDate(date) : '')
      .filter(Boolean)
      .join(' - ')
  }
  return formatSingleDate(selectedDate.value)
})

// 日历数据
const calendarDays = computed(() => {
  const year = currentDate.value.getFullYear()
  const month = currentDate.value.getMonth()
  const firstDay = new Date(year, month, 1)
  const lastDay = new Date(year, month + 1, 0)
  const days = []

  const firstDayOfWeek = firstDay.getDay()
  const prevMonthDays = (firstDayOfWeek - props.firstDayOfWeek + 7) % 7

  // 上月日期
  for (let i = prevMonthDays; i > 0; i--) {
    const date = new Date(year, month, 1 - i)
    days.push({
      date,
      isCurrentMonth: false,
      isDisabled: isDateDisabled(date)
    })
  }

  // 当月日期
  for (let i = 1; i <= lastDay.getDate(); i++) {
    const date = new Date(year, month, i)
    days.push({
      date,
      isCurrentMonth: true,
      isDisabled: isDateDisabled(date)
    })
  }

  // 下月日期
  const remainingDays = 42 - days.length
  for (let i = 1; i <= remainingDays; i++) {
    const date = new Date(year, month + 1, i)
    days.push({
      date,
      isCurrentMonth: false,
      isDisabled: isDateDisabled(date)
    })
  }

  return days
})

// 星期标题
const weekDays = computed(() => {
  const days = ['日', '一', '二', '三', '四', '五', '六']
  return [...days.slice(props.firstDayOfWeek), ...days.slice(0, props.firstDayOfWeek)]
})

// 判断日期是否禁用
const isDateDisabled = (date) => {
  if (!(date instanceof Date)) return true
  if (props.minDate && date < props.minDate) return true
  if (props.maxDate && date > props.maxDate) return true
  return props.disableDate(date)
}

// 选择日期
const selectDate = (day) => {
  if (!day.date || day.isDisabled) {
    emit('invalid', { reason: 'date disabled' })
    return
  }

  const newDate = new Date(day.date)

  if (props.isRange) {
    if (!Array.isArray(selectedDate.value)) {
      selectedDate.value = []
    }
    
    if (selectedDate.value.length === 0 || selectedDate.value.length === 2) {
      selectedDate.value = [newDate]
    } else {
      selectedDate.value = [selectedDate.value[0], newDate].sort((a, b) => a - b)
    }
  } else {
    selectedDate.value = newDate
  }

  emit('update:modelValue', selectedDate.value)
  emit('change', { value: selectedDate.value, isValid: true })
}

// 切换月份
const changeMonth = (delta) => {
  currentDate.value = new Date(
    currentDate.value.getFullYear(),
    currentDate.value.getMonth() + delta,
    1
  )
}

// 确认选择
const confirm = () => {
  emit('confirm', selectedDate.value)
  isOpen.value = false
  emit('close')
}

// 切换日历显示
const toggleCalendar = () => {
  if (props.disabled) return
  isOpen.value = !isOpen.value
  emit(isOpen.value ? 'open' : 'close')
}

// 监听数据变化
watch(() => props.modelValue, (newVal) => {
  if (props.isRange) {
    selectedDate.value = Array.isArray(newVal) 
      ? newVal.map(d => d instanceof Date ? new Date(d) : null)
      : []
  } else {
    selectedDate.value = newVal instanceof Date ? new Date(newVal) : null
  }
}, { immediate: true })
</script>

<template>
  <div :class="['date-picker', className]">
    <input
      type="text"
      :placeholder="placeholder"
      :value="formattedDate"
      @click="toggleCalendar"
      readonly
      :disabled="disabled"
    />
    
    <div v-if="isOpen || isInline" class="calendar">
      <div class="calendar-header">
        <button @click="changeMonth(-1)">&lt;</button>
        <span>{{ currentDate.getFullYear() }}年 {{ currentDate.getMonth() + 1 }}月</span>
        <button @click="changeMonth(1)">&gt;</button>
      </div>

      <div class="calendar-weeks">
        <div v-for="day in weekDays" :key="day" class="week-day">{{ day }}</div>
      </div>

      <div class="calendar-days">
        <div
          v-for="day in calendarDays"
          :key="day.date.getTime()"
          :class="[
            'calendar-day',
            {
              'is-current-month': day.isCurrentMonth,
              'is-disabled': day.isDisabled,
              'is-selected': selectedDate && (
                Array.isArray(selectedDate) 
                  ? selectedDate.some(d => d && d.getTime() === day.date.getTime())
                  : selectedDate.getTime() === day.date.getTime()
              )
            }
          ]"
          @click="selectDate(day)"
        >
          {{ day.date.getDate() }}
        </div>
      </div>

      <div v-if="showConfirmButton" class="calendar-footer">
        <button @click="confirm">{{ confirmText }}</button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.date-picker {
  display: inline-block;
  position: relative;
}

input {
  padding: 8px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  width: 200px;
  cursor: pointer;
}

.calendar {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 5px;
  background: white;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 1000;
}

.calendar-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px;
  border-bottom: 1px solid #ebeef5;
}

.calendar-weeks {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  border-bottom: 1px solid #ebeef5;
}

.week-day {
  padding: 8px;
  color: #606266;
}

.calendar-days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 2px;
  padding: 8px;
}

.calendar-day {
  padding: 8px;
  text-align: center;
  cursor: pointer;
  color: #606266;
}

.calendar-day:hover:not(.is-disabled) {
  background-color: #f5f7fa;
}

.is-current-month {
  color: #303133;
}

.is-selected {
  background-color: #409eff;
  color: white;
}

.is-disabled {
  color: #c0c4cc;
  cursor: not-allowed;
  background-color: #f5f7fa;
}

.calendar-footer {
  padding: 8px;
  text-align: right;
  border-top: 1px solid #ebeef5;
}

button {
  padding: 6px 12px;
  background: #409eff;
  border: none;
  border-radius: 4px;
  color: white;
  cursor: pointer;
}

button:hover {
  background: #66b1ff;
}

.is-inline {
  position: static;
  margin-top: 0;
}
</style>